package com.rs.game.player.controlers;

import java.util.Random;
import com.rs.Settings;
import com.rs.cache.loaders.ItemDefinitions;
import com.rs.game.Animation;
import com.rs.game.Entity;
import com.rs.game.ForceMovement;
import com.rs.game.World;
import com.rs.game.WorldObject;
import com.rs.game.WorldTile;
import com.rs.game.item.Item;
import com.rs.game.npc.NPC;
import com.rs.game.player.Player;
import com.rs.game.player.Skills;
import com.rs.game.player.actions.thieving.Thieving;
import com.rs.game.player.content.grandExchange.GrandExchange;
import com.rs.game.tasks.WorldTask;
import com.rs.game.tasks.WorldTasksManager;
import com.rs.net.decoders.handlers.ButtonHandler;
import com.rs.utils.Misc;
import com.rs.utils.Utils;

public class Wilderness extends Controler {

	/**
	 * @author WM
	 * 
	 * BountyHunter Target System implemented in the Wilderness Controller.
	 */
	
	/**
	 * TODO: Containers [More or less done], Safe, Correct timing of tasks [In progress], add PvP items.
	 */
	@Override
	public void start() {
		checkBoosts(player);
		refresh();
	}

	/**
	 * Arrays and integers.
	 */
	private int[][] LOW_REWARD = { { 14888, 0 }, { 14889, 0 }, { 14890, 0 }, { 14891, 0 }, { 14892, 0 } };
	private int[][] MEDIUM_REWARD = { { 14883, 0 }, { 14884, 0 }, { 14885, 0 }, { 14886, 0 } };
	private int[][] HIGH_REWARD = { { 14878, 0 }, { 14879, 0 }, { 14880, 0 }, { 14881, 0 }, { 14882, 0 } };
	private int[][] EXTREMELY_HIGH_REWARD = { { 14876, 0 }, { 14877, 0 } };
	private boolean searching, gainingEP;
	private boolean showingSkull;
	private int DROP_WEALTH = 0;

	/**
	 * Checks if the target/player left the wilderness and therefore has 3 minutes to return or target is lost.
	 * @return
	 */
	public boolean checkIfinSafe() {
		if (playerHasTarget(player)) 
		{
			if (player.getTemporaryAttributes().get("safeTimerStarted") == null)
				player.getTemporaryAttributes().put("safeTimerStarted", Boolean.FALSE);
			if (player.getTemporaryAttributes().get("safeTimerStarted") == Boolean.FALSE) {
				player.getTemporaryAttributes().put("safeTimerStarted", Boolean.TRUE);
				player.getPackets().sendGameMessage("Your target has 3 minutes to return to the wilderness.");
				player.getPackets().sendGameMessage("<col=FF0000>Warning!</col> You have 3 minutes to re-enter the wilderness or you lose your target.");
				WorldTasksManager.schedule(new WorldTask() {
					int ticks; 
					@Override
					public void run() {
						ticks++;
						if (ticks == 5) 
						{
							stop();
							if (isAtWild(player)) 
							{
								player.getTemporaryAttributes().put("safeTimerStarted", Boolean.FALSE);
							} else 
							{
								resetSingleTarget(player);
								player.getPackets().sendGameMessage("You spent too long in the safe area so you lose your target.");
								player.getBountyHunterTarget().getPackets().sendGameMessage("Your target spent too long in the safe area so you lose them as a target.");
								player.getTemporaryAttributes().put("safeTimerStarted", Boolean.FALSE);
							}
						}
					}
				},0 , 60);
			}
		} else 
		{
			forceClose();
		}
		return false;
	}

	/**
	 * Calculates and return the correct value.
	 * @return
	 */
	private int calculateConfigValueOfLikeliHood() {
		if (player.getTargetMeter() >= 8)
		{
			player.setTargetMeter(8);
			return 60;
		} else if (player.getTargetMeter() == 7)
		{
			return 56;
		} else if (player.getTargetMeter() == 6)
		{
			return 48;
		} else if (player.getTargetMeter() == 5) 
		{
			return 40;
		} else if (player.getTargetMeter() == 4) 
		{
			return 32;
		} else if (player.getTargetMeter() == 3) 
		{
			return 24;
		} else if (player.getTargetMeter() == 2)
		{
			return 16;
		} else if (player.getTargetMeter() == 1) 
		{
			return 8;
		}
		return 0;
	}

	/**
	 * Sloppy method to refresh all interfaces every game tick and check to initiate methods. 
	 */
	@Override 
	public boolean refresh() {
		WorldTasksManager.schedule(new WorldTask() {

			@Override
			public void run() {
				if (isAtWild(player)) 
				{
					player.getInterfaceManager().setWindowInterface(player.getInterfaceManager().hasRezizableScreen() ? 11 : 0, 591);//BountyHunter target overlay.
					if (player.getInterfaceManager().hasRezizableScreen())
					{
						player.getPackets().sendIComponentText(746, 17, getLevelDifference(player, false) + " - " + getLevelDifference(player, true));//Levels
						player.getPackets().sendIComponentText(746, 164, "EP: <col=" + getEPCol(player) + ">" + player.getEarnedPotential() + "%");//EP
						player.getPackets().sendHideIComponent(745, 6, false);//hot zone icon shown
						player.getPackets().sendHideIComponent(745, 3, true);//safe zone icon hidden
					} else 
					{
						player.getPackets().sendIComponentText(548, 12, getLevelDifference(player, false) + " - " + getLevelDifference(player, true));//Levels
						player.getPackets().sendIComponentText(548, 13, "EP: <col=" + getEPCol(player) + ">" + player.getEarnedPotential() + "%");//EP
						player.getPackets().sendHideIComponent(745, 6, false);//hot zone icon shown
						player.getPackets().sendHideIComponent(745, 3, true);//safe zone icon hidden
					}
					if (!player.hasBountyHunterTarget() && ((player.getTemporaryAttributes().get("targetPercentTimerStarted") == Boolean.FALSE) || (player.getTemporaryAttributes().get("targetPercentTimerStarted") == null)) && player.getTargetMeter() < 8) {
						increaseTargChance();
					}
					if (canGetEP() && !gainingEP && player.getEarnedPotential() < 100) {
						startGainingEP();
					}
					if (!player.hasBountyHunterTarget() && World.getPlayers().size() >= 2 && !searching) {
						searchForTarget(player);
					}
					if (!player.hasBountyHunterTarget())
						player.getPackets().sendIComponentText(591, 8, "None");//Target String name
					else 
					{
						player.getPackets().sendIComponentText(591, 8, ""+Misc.formatPlayerNameForDisplay(player.getBountyHunterTarget().getUsername()));//Target String name
					}
					player.getVarsManager().sendVar(1410, calculateConfigValueOfLikeliHood());//32 = half, 

				} else {
					if (player.getInterfaceManager().hasRezizableScreen())
					{
						player.getPackets().sendIComponentText(746, 17, "");//Levels
						player.getPackets().sendIComponentText(746, 164, "");//EP
						player.getPackets().sendHideIComponent(745, 6, true);//hot zone icon shown
						player.getPackets().sendHideIComponent(745, 3, false);//safe zone icon hidden
					} else 
					{
						player.getPackets().sendIComponentText(548, 12, "");//Levels
						player.getPackets().sendIComponentText(548, 13, "");//EP
						player.getPackets().sendHideIComponent(745, 6, true);//hot zone icon shown
						player.getPackets().sendHideIComponent(745, 3, false);//safe zone icon hidden
					}
					checkIfinSafe();
				}
			}
		}, 0, 1);
		return false;
	}

	/*@Override
	public void forceClose() {
		if (player.getInterfaceManager().hasRezizableScreen()) {
			player.getPackets().sendIComponentText(548, 12, "");//Levels
			player.getPackets().sendIComponentText(548, 13, "");//EP
		} else {
			player.getPackets().sendIComponentText(746, 14, "");//Levels
			player.getPackets().sendIComponentText(746, 161, "");//EP
		}
		player.getPackets().sendHideIComponent(745, 6, true);//Hot zone icon
		if (playerHasTarget(player))
			resetSingleTarget(player);
		player.getAppearence().generateAppearenceData();
		player.getControlerManager().getControler().removeControler();
		return;
	}*/

	/*public boolean sendDeath(Player player) {
		if (getPlayer().getCombatExecutor().getLastKiller() != null) {
			if (getPlayer().getCombatExecutor().getLastKiller().isPlayer()) {
					handleReward();
				if (getPlayer().getDamageManager().getKiller() == getPlayer().getBountyHunterTarget())
					resetDuoTarget();
			}
		}
		return false;
	}*/

	private int getLevelDifference(Player p, boolean up) {
		int difference = 0;
		if (up)
			difference = (int) p.getSkills().getCombatLevelWithoutSummoning() + p.getWildernessLevel(); 
		else 
			difference = (int) p.getSkills().getCombatLevelWithoutSummoning() - p.getWildernessLevel();
		return difference < 3 ? 3 : difference > 126 && up ? 126 : difference;
	}

	private long getRiskedWealth() {
		return calculateRiskedWealth();
	}

	private long calculateRiskedWealth() {
		boolean skulled = player.hasSkull();
		Integer[][] slots = ButtonHandler.getItemSlotsKeptOnDeath(player, true,
				skulled, player.getPrayer().isProtectingItem());
		Item[][] items = ButtonHandler.getItemsKeptOnDeath(player, slots);
		long carriedWealth = 0;
		long riskedWealth = 0;
		for (Item item : items[1]) {
			if (carriedWealth + riskedWealth + GrandExchange.getPrice(item.getId()) > Integer.MAX_VALUE) {
				carriedWealth = Integer.MAX_VALUE;
				break;
			}
			carriedWealth = riskedWealth += GrandExchange.getPrice(item.getId());
		}
		for (Item item : items[0]) {
			if (carriedWealth + GrandExchange.getPrice(item.getId()) > Integer.MAX_VALUE) {
				carriedWealth = Integer.MAX_VALUE;
				break;
			}
			carriedWealth += GrandExchange.getPrice(item.getId());
		}
		return riskedWealth;
	}

	/**
	 * Checks if the player can get ep. 
	 * @return
	 */
	private boolean canGetEP() {
		return (getRiskedWealth() >= 76000) && player.getEarnedPotential() < 100 && isAtWild(player);
	}

	/**
	 * WorldTask so the player can gain EP.
	 */
	private void startGainingEP() {
		gainingEP = true;
		if (player.getTemporaryAttributes().get("epTimerStarted") == null)
			player.getTemporaryAttributes().put("epTimerStarted", Boolean.FALSE);
		if (player.getTemporaryAttributes().get("epTimerStarted") == Boolean.FALSE) {
			player.getTemporaryAttributes().put("epTimerStarted", Boolean.TRUE);
			WorldTasksManager.schedule(new WorldTask() {
				@Override
				public void run() {
					if (canGetEP()) {
						if (player.getEarnedPotential() == 100) {
							stop();
							System.out.println("Stopped gaining EP.");
							gainingEP = false;
						}
						if (player.getEarnedPotential() < 100) {
							player.setEarnedPotential((player.getEarnedPotential() <= 75 ? player.getEarnedPotential() + 25 : player.getEarnedPotential() + (100 - player.getEarnedPotential())));
							player.getTemporaryAttributes().put("epTimerStarted", Boolean.FALSE);
						}
					} else {
						player.getTemporaryAttributes().put("epTimerStarted", Boolean.FALSE);
					}
				}
			},0 , 300);
		}
	}

	private boolean canEarnTargetPotential() {
		return isAtWild(player);
	}

	private boolean canObtainTarget(Player p) {
		if (p.getTargetMeter() >= 6) {
			return true;
		}
		return false;
	}

	private boolean playerHasTarget(Player player) {
		return player.hasBountyHunterTarget();
	}

	/**
	 * Increasing 1/8 on targetmeter every x-amount of time. Checks if not running twice.
	 */
	private void increaseTargChance() {
		if (player.getTemporaryAttributes().get("targetPercentTimerStarted") == null)
			player.getTemporaryAttributes().put("targetPercentTimerStarted", Boolean.FALSE);
		if (player.getTemporaryAttributes().get("targetPercentTimerStarted") == Boolean.FALSE) {
			player.getTemporaryAttributes().put("targetPercentTimerStarted", Boolean.TRUE);
			WorldTasksManager.schedule(new WorldTask() {
				int ticks = 0;
				@Override
				public void run() {
					ticks++;
					if (ticks == 5) {
						if (player.hasBountyHunterTarget() || isAtWildSafe() || player.getTargetMeter() == 8) 
						{
							stop();
							player.getTemporaryAttributes().put("targetPercentTimerStarted", Boolean.FALSE);
						}
						if (canEarnTargetPotential())
						{
							if (player.getTargetMeter() < 8)
							{
								player.setTargetMeter(player.getTargetMeter() + 1);
								calculateConfigValueOfLikeliHood();
								player.getTemporaryAttributes().put("targetPercentTimerStarted", Boolean.FALSE);
							}
						} else 
						{
							player.getTemporaryAttributes().put("targetPercentTimerStarted", Boolean.FALSE);
						}
					}

				}
			}, 0, 60);//one tick is approximately 30 game ticks. 
		}
	}


	private void searchForTarget(Player p) {
		System.out.println("Searching for target..");
		WorldTasksManager.schedule(new WorldTask() {
			@Override
			public void run() {
				if (player.hasBountyHunterTarget() || World.getPlayers().size() < 2) {
					System.out.println("I am in wildy!");
					stop();
					searching = false;
					System.out.println("Stopped searching for a target.");
				} else if (p != null && !p.isDead()) {
					searching = true;
					if (canObtainTarget(p)) {
						System.out.println("ObtainTarg:"+canObtainTarget(p));

						for (Player target : World.getPlayers()) {
							if (target != null) {
								if (target != p) {

									if (isAtWild(target) && isAtWild(target) && target.getTargetMeter() >= 4 && isTargetRange(target)) {
										System.out.println("In wild:"+isAtWild(target));
										System.out.println("In range:"+isTargetRange(target));
										System.out.println("TM:"+target.getTargetMeter());

										if (!playerHasTarget(target) && !playerHasTarget(p)) {
											System.out.println("PHT:"+player.hasBountyHunterTarget());
											System.out.println("THT:"+target.hasBountyHunterTarget());

											setTarget(p, target);
											setTarget(target, p);
										}
									}
								}
							}
						}	
					}

				}
			}
		}, 5, 10);
	}

	private boolean isTargetRange(Player targ) {
		int combatLev = player.getSkills().getCombatLevelWithoutSummoning();
		if (getLevelDifference(targ, false) <= combatLev && getLevelDifference(targ, true) >= combatLev)
			return true;
		return false;
	}

	private void setTarget(Player player, Player target) {
		player.setHasBounterHunterTarget(true);
		player.setBountyHunterTarget(target);
		player.getHintIconsManager().addHintIcon(target, 1, -1, false);
		player.getPackets().sendIComponentText(591, 8, ""+ Misc.formatPlayerNameForDisplay(target.getUsername()));
		target.getPackets().sendIComponentText(591, 8, ""+ Misc.formatPlayerNameForDisplay(player.getUsername()));
		player.getPackets().sendGameMessage("You have been assigned a target, you should hunt down " + Misc.formatPlayerNameForDisplay(target.getUsername()) + "!");
	}

	private void resetDuoTarget() {
		removeHintIcon();
		searching = false;
		gainingEP = false; 
		player.getTemporaryAttributes().put("targetPercentTimerStarted", Boolean.FALSE);		
		player.getBountyHunterTarget().setHasBounterHunterTarget(false);
		player.getBountyHunterTarget().setBountyHunterTarget(null);
		player.getBountyHunterTarget().setTargetMeter(0);
		player.getBountyHunterTarget().getVarsManager().sendVar(1410, 0);
		player.setHasBounterHunterTarget(false);
		player.setBountyHunterTarget(null);
		player.setTargetMeter(0);
		player.getVarsManager().sendVar(1410, 0);

	}

	private void resetSingleTarget(Player player) {
		removeHintIcon();
		player.getBountyHunterTarget().setTargetMeter(0);
		player.getBountyHunterTarget().setBountyHunterTarget(null);
		player.getBountyHunterTarget().setHasBounterHunterTarget(false);
		player.setBountyHunterTarget(null);
		player.setHasBounterHunterTarget(false);
	}

	public void removeHintIcon() {
		player.getHintIconsManager().removeUnsavedHintIcon();
		player.getBountyHunterTarget().getHintIconsManager().removeUnsavedHintIcon();
	}

	private String getEPCol(Player p) {
		if (p.getEarnedPotential() >= 70)
			return "33CC00";
		if (p.getEarnedPotential() >= 35 && p.getEarnedPotential() < 70)
			return "FFFF00";
		if (p.getEarnedPotential() >= 20 && p.getEarnedPotential() < 35)
			return "FF9900";
		return "FF0000";
	}

	private void handleReward(Player killer) {
		if (killer != null) {
			boolean targetKill = (killer.getBountyHunterTarget() == player ? true : false);
			int EP = killer.getEarnedPotential();
			getReward(killer, EP, targetKill);
			System.out.println("TargetKill:"+targetKill);
		}
	}

	/**
	 * Rewarding the killer.
	 * @param killer
	 * @param ep
	 * @param targetKill
	 */
	private void getReward(Player killer, int ep, boolean targetKill) {
		double rewardPotential = ((new Random().nextDouble() * ep) / 100);
		if (targetKill)
			getTargetKillArtifact(rewardPotential * 5.756);
		else
			getArtifact(rewardPotential);
		int decreaseAmount = getEPDecrease(DROP_WEALTH) + Misc.random(getEPDecrease(DROP_WEALTH));
		if (killer.getEarnedPotential() - decreaseAmount < 0)
			killer.setEarnedPotential(0);
		else
			killer.setEarnedPotential(killer.getEarnedPotential() - decreaseAmount);
		if (killer.getControlerManager().getControler() instanceof Wilderness)
			killer.getPackets().sendIComponentText(548, 10, "EP: <col=" + getEPCol(killer) + ">" + killer.getEarnedPotential() + "%");//EP
	}

	/**
	 * Artifact from array based on not killing the target.
	 * @param rewardPotential
	 */
	private void getArtifact(double rewardPotential) {
		if (rewardPotential >= 0.100 && rewardPotential < 0.350)
			sendDrop(RandomizeDrop(MEDIUM_REWARD), MEDIUM_REWARD);
		else if (rewardPotential >= 0.300 && rewardPotential < 0.520)
			sendDrop(RandomizeDrop(HIGH_REWARD), HIGH_REWARD);
		else if (rewardPotential >= 0.500)
			sendDrop(RandomizeDrop(EXTREMELY_HIGH_REWARD), EXTREMELY_HIGH_REWARD);
		else
			sendDrop(RandomizeDrop(LOW_REWARD), LOW_REWARD);
	}

	/**
	 * Artifact from array based on a killing the target.
	 * @param rewardPotential
	 */
	private void getTargetKillArtifact(double rewardPotential) {
		if (rewardPotential >= 0.300)
			sendDrop(RandomizeDrop(HIGH_REWARD), HIGH_REWARD);
		else if (rewardPotential >= 3.500)
			sendDrop(RandomizeDrop(EXTREMELY_HIGH_REWARD), EXTREMELY_HIGH_REWARD);
		else {
			sendDrop(RandomizeDrop(LOW_REWARD), LOW_REWARD);
			sendDrop(RandomizeDrop(MEDIUM_REWARD), MEDIUM_REWARD);
		}
	}

	/**
	 * Sending the actual drop.
	 * @param item
	 * @param array
	 */

	private void sendDrop(int item, int [][] array) {
		int amount = 0;
		for (int i = 0; i < array.length; i++)
			if (array[i][0] == item)
				amount = 1 + Utils.random(array[i][1]);
		World.addGroundItem(new Item(item, amount), player.getLastWorldTile());
		DROP_WEALTH += (ItemDefinitions.getItemDefinitions(item).getValue() * amount);
	}

	/**
	 * Randomizing drop.
	 * @param array
	 * @return
	 */
	private int RandomizeDrop(int[][] array) {
		return array[(int) (Math.random() * array.length)][0];
	}

	/**
	 * EP decrease.
	 * @param totalValue
	 * @return
	 */
	private int getEPDecrease(int totalValue) {
		if (totalValue > 10000 && totalValue <= 50000)
			return 4;
		else if (totalValue > 50000 && totalValue <= 100000)
			return 6;
		else if (totalValue > 100000 && totalValue <= 200000)
			return 8;
		else if (totalValue > 200000 && totalValue <= 500000)
			return 11;
		else if (totalValue > 500000 && totalValue <= 1000000)
			return 16;
		else if (totalValue > 1000000 && totalValue <= 2000000)
			return 24;
		else if (totalValue >= 2000000)
			return 30;
		return 2;
	}

	public static void checkBoosts(Player player) {
		boolean changed = false;
		int level = player.getSkills().getLevelForXp(Skills.ATTACK);
		int maxLevel = (int) (level + 5 + (level * 0.15));
		if (maxLevel < player.getSkills().getLevel(Skills.ATTACK)) {
			player.getSkills().set(Skills.ATTACK, maxLevel);
			changed = true;
		}
		level = player.getSkills().getLevelForXp(Skills.STRENGTH);
		maxLevel = (int) (level + 5 + (level * 0.15));
		if (maxLevel < player.getSkills().getLevel(Skills.STRENGTH)) {
			player.getSkills().set(Skills.STRENGTH, maxLevel);
			changed = true;
		}
		level = player.getSkills().getLevelForXp(Skills.DEFENCE);
		maxLevel = (int) (level + 5 + (level * 0.15));
		if (maxLevel < player.getSkills().getLevel(Skills.DEFENCE)) {
			player.getSkills().set(Skills.DEFENCE, maxLevel);
			changed = true;
		}
		level = player.getSkills().getLevelForXp(Skills.RANGE);
		maxLevel = (int) (level + 5 + (level * 0.1));
		if (maxLevel < player.getSkills().getLevel(Skills.RANGE)) {
			player.getSkills().set(Skills.RANGE, maxLevel);
			changed = true;
		}
		level = player.getSkills().getLevelForXp(Skills.MAGIC);
		maxLevel = level + 5;
		if (maxLevel < player.getSkills().getLevel(Skills.MAGIC)) {
			player.getSkills().set(Skills.MAGIC, maxLevel);
			changed = true;
		}
		if (changed)
			player.getPackets().sendGameMessage("Your extreme potion bonus has been reduced.");
	}

	@Override
	public boolean login() {
		moved();
		return false;
	}

	@Override
	public boolean keepCombating(Entity target) {
		if (target instanceof NPC)
			return true;
		if (!canAttack(target))
			return false;
		if (target.getAttackedBy() != player && player.getAttackedBy() != target)
			player.setWildernessSkull();
		if (player.getCombatDefinitions().getSpellId() <= 0 && Utils.inCircle(new WorldTile(3105, 3933, 0), target, 24)) {
			player.getPackets().sendGameMessage("You can only use magic in the arena.");
			return false;
		}
		return true;
	}

	@Override
	public boolean canAttack(Entity target) {
		if (target instanceof Player) {
			Player p2 = (Player) target;
			if (player.isCanPvp() && !p2.isCanPvp()) {
				player.getPackets().sendGameMessage("That player is not in the wilderness.");
				return false;
			}
			if (canHit(target))
				return true;
			return false;
		}
		return true;
	}

	@Override
	public boolean canHit(Entity target) {
		if (target instanceof NPC)
			return true;
		Player p2 = (Player) target;
		if (Math.abs(player.getSkills().getCombatLevel() - p2.getSkills().getCombatLevel()) > getWildLevel())
			return false;
		return true;
	}

	@Override
	public boolean processMagicTeleport(WorldTile toTile) {
		if (getWildLevel() > 20) {
			player.getPackets().sendGameMessage("A mysterious force prevents you from teleporting.");
			return false;
		}
		if (player.getTeleBlockDelay() > Utils.currentTimeMillis()) {
			player.getPackets().sendGameMessage("A mysterious force prevents you from teleporting.");
			return false;
		}
		return true;

	}

	@Override
	public boolean processItemTeleport(WorldTile toTile) {
		if (getWildLevel() > 30) {
			player.getPackets().sendGameMessage("A mysterious force prevents you from teleporting.");
			return false;
		}
		if (player.getTeleBlockDelay() > Utils.currentTimeMillis()) {
			player.getPackets().sendGameMessage("A mysterious force prevents you from teleporting.");
			return false;
		}
		return true;
	}

	@Override
	public boolean processObjectTeleport(WorldTile toTile) {
		if (player.getTeleBlockDelay() > Utils.currentTimeMillis()) {
			player.getPackets().sendGameMessage("A mysterious force prevents you from teleporting.");
			return false;
		}
		return true;
	}

	public void showSkull() {
		player.getInterfaceManager().setWindowInterface(player.getInterfaceManager().hasRezizableScreen() ? 11 : 0, 591);//BountyHunter target overlay.
		if (!player.hasBountyHunterTarget())
			player.getPackets().sendIComponentText(591, 8, "None");//Target String name
		else 
		{
			player.getPackets().sendIComponentText(591, 8, ""+Misc.formatPlayerNameForDisplay(player.getBountyHunterTarget().getUsername()));//Target String name
		}
		refresh();
	}

	public static final boolean isAtDitch(WorldTile tile) {
		if (tile.getRegionId() == 10057)
			return true;
		return (tile.getX() >= 2940 && tile.getX() <= 3395 && tile.getY() <= 3524 && tile.getY() >= 3523 || tile.getX() >= 3084 && tile.getX() <= 3092 && tile.getY() >= 3929 && tile.getY() <= 3937);
	}

	public static boolean isDitch(int id) {
		return id >= 1440 && id <= 1444 || id >= 65076 && id <= 65087;
	}

	@Override
	public boolean processObjectClick1(final WorldObject object) {
		if (isDitch(object.getId())) {
			player.lock();
			player.setNextAnimation(new Animation(6132));
			final WorldTile toTile = new WorldTile(object.getRotation() == 1 || object.getRotation() == 3 ? object.getX() + 2 : player.getX(), object.getRotation() == 0 || object.getRotation() == 2 ? object.getY() - 1 : player.getY(), object.getPlane());

			player.setNextForceMovement(new ForceMovement(new WorldTile(player), 1, toTile, 2, object.getRotation() == 0 || object.getRotation() == 2 ? ForceMovement.SOUTH : ForceMovement.EAST));
			WorldTasksManager.schedule(new WorldTask() {
				@Override
				public void run() {
					player.setNextWorldTile(toTile);
					player.faceObject(object);
					removeIcon();
					removeControler();
					player.resetReceivedDamage();
					player.unlock();
				}
			}, 2);
			return false;
		} else if (object.getId() == 2557 || object.getId() == 65717) {
			player.getPackets().sendGameMessage("It seems like it is locked, maybe you should try something else.");
			return false;
		}
		return true;
	}

	@Override
	public boolean processObjectClick2(final WorldObject object) {
		if (object.getId() == 2557 || object.getId() == 65717) {
			Thieving.pickDoor(player, object);
			return false;
		}
		return true;
	}

	@Override
	public void sendInterfaces() {
		if (isAtWild(player))
			showSkull();
	}

	@Override
	public boolean sendDeath() {
		player.lock(7);
		player.stopAll();
		WorldTasksManager.schedule(new WorldTask() {
			int loop;

			@Override
			public void run() {
				if (loop == 0) {
					player.setNextAnimation(new Animation(836));
				} else if (loop == 1) {
					player.getPackets().sendGameMessage("Oh dear, you have died.");
				} else if (loop == 3) {
					Player killer = player.getMostDamageReceivedSourcePlayer();
					if (killer != null) {
						killer.removeDamage(player);
						killer.increaseKillCount(player);
						killer.setAttackedByDelay(Utils.currentTimeMillis() + 8000); // immunity
					}
					player.sendItemsOnDeath(killer);
					handleReward(killer);
					boolean targetKill = (killer.getBountyHunterTarget() == player ? true : false);
					if (targetKill) {
						System.out.println("Resetted Duo targets.");
						resetDuoTarget();
					}
					player.reset();
					player.setNextWorldTile(Settings.RESPAWN_PLAYER_LOCATION); // edgevile
					player.setNextAnimation(new Animation(-1));
				} else if (loop == 4) {
					removeIcon();
					removeControler();
					player.getPackets().sendMusicEffect(90);
					stop();
				}
				loop++;
			}
		}, 0, 1);
		return false;
	}

	@Override
	public void magicTeleported(int teleType) {
		if (!isAtWild(player.getNextWorldTile())) {
			player.setCanPvp(false);
			removeIcon();
			removeControler();
		}
	}

	@Override
	public void moved() {//TODO
		boolean isAtWild = isAtWild(player);
		boolean isAtWildSafe = isAtWildSafe();
		if (!showingSkull && isAtWild && !isAtWildSafe) {
			showingSkull = true;
			player.setCanPvp(true);
			showSkull();
			player.getAppearence().generateAppearenceData();
		} else if (showingSkull && (isAtWildSafe || !isAtWild)) {
			if (playerHasTarget(player)) {
				checkIfinSafe();
			}
			removeIcon();
		} else if (!isAtWildSafe && !isAtWild) {
			player.setCanPvp(false);
			removeIcon();
			removeControler();
		} 
	}

	public void removeIcon() {
		if (showingSkull) {
			showingSkull = false;
			player.setCanPvp(false);
			player.getInterfaceManager().removeOverlay(false);
			player.getAppearence().generateAppearenceData();
			player.getEquipment().refresh(null);
		}
	}

	@Override
	public boolean logout() {
		return false; 
	}

	@Override
	public void forceClose() {
		removeIcon();
	}

	public static final boolean isAtWild(WorldTile tile) {
		return (tile.getX() >= 3011 && tile.getX() <= 3132 && tile.getY() >= 10052 && tile.getY() <= 10175) 
				|| (tile.getX() >= 2940 && tile.getX() <= 3395 && tile.getY() >= 3525 && tile.getY() <= 4000) || (tile.getX() >= 3264 && tile.getX() <= 3279 && tile.getY() >= 3279 && tile.getY() <= 3672) || (tile.getX() >= 2756 && tile.getX() <= 2875 && tile.getY() >= 5512 && tile.getY() <= 5627) || (tile.getX() >= 3158 && tile.getX() <= 3181 && tile.getY() >= 3679 && tile.getY() <= 3697) || (tile.getX() >= 3280 && tile.getX() <= 3183 && tile.getY() >= 3885 && tile.getY() <= 3888) || (tile.getX() >= 3012 && tile.getX() <= 3059 && tile.getY() >= 10303 && tile.getY() <= 10351);
	}

	public boolean isAtWildSafe() {
		return (player.getX() >= 2940 && player.getX() <= 3395 && player.getY() <= 3524 && player.getY() >= 3523);
	}

	public int getWildLevel() {
		if (player.getY() > 9900)
			return (player.getY() - 9912) / 8 + 1;
		return (player.getY() - 3520) / 8 + 1;
	}

}
